﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using static 摸鱼.全局类;
using System.Threading;
using System.Windows.Forms;
using System.IO.MemoryMappedFiles;
using static 摸鱼.键鼠.钩子;
using System.Runtime.CompilerServices;

namespace 摸鱼
{
    public class 键鼠
    {
        public static class 钩子
        {
            public static event Action<List<int>, bool> 键盘Click; // 键盘按下事件
            public static event Action<List<int>, bool> 鼠标Click; // 键盘按下事件
            public static event Action<Point> MouseMove; // 鼠标移动事件
            public static event Action<MouseButtons> MouseDown; // 鼠标按下事件
            public static event Action<MouseButtons> MouseUP; // 鼠标弹起事件
            public static event Action<Keys> MouseWheel; // 鼠标滚轮事件

            public static void Start()
            {
                Process q = Process.Start("Moyu后台服务.exe");

                共享内存2.初始化();
                MoyuThreadPool.Post(KeyboardProc);
                MoyuThreadPool.Post(MouseProc);
            }
            public static List<键盘按键.Data> 键盘按键s = new();
            private static void KeyboardProc()
            {
                while (!键盘按键.isDispose)
                {
                    键盘按键s = 键盘按键.GetData();
                    var data = 键盘按键s.FirstOrDefault();
                    List<int> ints = new(键盘按键s.Select(x => x.Keys));
                    if (data == default)
                        MoyuThreadPool.Post(() => 键盘Click.Invoke(ints, default));
                    else
                        MoyuThreadPool.Post(() => 键盘Click.Invoke(ints, data.KeyDown));
                }
            }
            public static class 键盘按键
            {
                private static int ID;
                public static bool isDispose = false;
                private static Mutex ___互斥锁;
                private unsafe static Data* data;
                private static int maxAppnum = 10;
                private static int maxArrayLength = 50;
                private static Mutex[] 工作钥匙 = new Mutex[maxAppnum];
                private static MemoryMappedFile[] 共享内存 = new MemoryMappedFile[5];
                private static EventWaitHandle[] 写入事件 = new EventWaitHandle[maxAppnum];

                static 键盘按键()
                {
                    ___互斥锁 = new Mutex(false, nameof(键盘按键) + 1, out var createdNew);
                    共享内存[0] = MemoryMappedFile.CreateOrOpen(nameof(键盘按键) + 2, Marshal.SizeOf(typeof(Data)) * maxArrayLength);
                    共享内存[1] = MemoryMappedFile.CreateOrOpen(nameof(键盘按键) + 3, Marshal.SizeOf(typeof(bool)) * maxAppnum);

                    if (createdNew)
                        共享内存[1].CreateViewAccessor().WriteArray(0, new bool[maxAppnum], 0, maxAppnum);

                    if (Process.GetCurrentProcess().ProcessName == "Moyu后台服务")
                    {
                        for (int i = 0; i < maxAppnum; i++)
                        {
                            写入事件[i] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(键盘按键) + (i + 10));
                            工作钥匙[i] = new Mutex(false, nameof(键盘按键) + (i + 20));
                        }
                    }
                    else
                    {
                        bool[] apps = new bool[maxAppnum];
                        共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);

                        ___互斥锁.WaitOne();
                        for (int i = 0; i < maxAppnum; i++)
                            if (!apps[i])
                            {
                                ID = i;
                                apps[i] = true;
                            }
                        ___互斥锁.ReleaseMutex();

                        写入事件[ID] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(键盘按键) + (ID + 10));
                        工作钥匙[ID] = new Mutex(false, nameof(键盘按键) + (ID + 20));
                        工作钥匙[ID].WaitOne();
                    }

                    unsafe
                    {
                        data = GetPtr<Data>(0);
                    }
                }
                [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                public unsafe static List<Data> GetData()
                {
                    工作钥匙[ID].ReleaseMutex();
                    写入事件[ID].WaitOne();
                    工作钥匙[ID].WaitOne();
                    写入事件[ID].Reset();

                    List<Data> list = new List<Data>();
                    for (int i = 0; i < maxArrayLength; i++)
                    {
                        if (data[i] != default)
                            list.Add(data[i]);
                        else
                            return list;
                    }
                    return list;
                }
                [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                public unsafe static void SetData(Span<Data> datas, bool keydown)
                {
                    for (int i = 0; i < maxArrayLength; i++)
                    {
                        if (i < datas.Length)
                            data[i] = datas[i];
                        else
                            data[i] = default;
                    }
                    data[0].KeyDown = keydown;

                    for (int i = 0; i < maxAppnum; i++)
                        写入事件[i].Set();

                    for (int i = 0; i < maxAppnum; i++)
                    {
                        工作钥匙[i].WaitOne();
                        工作钥匙[i].ReleaseMutex();
                    }
                }
                public unsafe static void Dispose()
                {
                    isDispose = true;
                    写入事件[ID].Close();
                    工作钥匙[ID].Close();

                    ___互斥锁.WaitOne();
                    bool[] apps = new bool[maxAppnum];
                    共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);
                    apps[ID] = false;
                    共享内存[1].CreateViewAccessor().WriteArray(0, apps, 0, maxAppnum);
                    ___互斥锁.ReleaseMutex();

                    foreach (var item in 共享内存)
                    {
                        if (item != null)
                            item.Dispose();
                    }
                    ___互斥锁.Dispose();
                }
                public struct Data
                {
                    public int Keys;
                    public bool KeyDown;
                    public Data(int Keys)
                    {
                        this.Keys = Keys;
                    }
                    public static bool operator ==(Data my1, Data my2)
                    {
                        return my1.Equals(my2);
                    }
                    public static bool operator !=(Data my1, Data my2)
                    {
                        return !(my1 == my2);
                    }
                }
                private unsafe static T* GetPtr<T>(int index)
                {
                    byte* v = default;
                    共享内存[index].CreateViewAccessor().SafeMemoryMappedViewHandle.AcquirePointer(ref v);
                    return (T*)v;
                }
            }

            public static List<鼠标按键.Data> 鼠标按键s = new();
            private static void MouseProc()
            {
                while (!鼠标按键.isDispose)
                {
                    鼠标按键s = 鼠标按键.GetData();
                    var data = 鼠标按键s.FirstOrDefault();
                    List<int> ints = new(鼠标按键s.Select(x => x.Keys));
                    //Debug.WriteLine(string.Join(',', ints));
                    if (data == default)
                        MoyuThreadPool.Post(() => 鼠标Click?.Invoke(ints, default));
                    else
                        MoyuThreadPool.Post(() => 鼠标Click?.Invoke(ints, data.KeyDown));
                }
            }
            public static class 共享内存2
            {
                public static string mapName = "Moyu2";
                public static long 数据大小 = Marshal.SizeOf(typeof(_数据));
                public static MemoryMappedFile mmf;
                public static MemoryMappedViewAccessor 访问器;
                public static _数据 数据 = new();
                public struct _数据
                {
                    public bool 鼠标锁;
                }
                public static void 初始化()
                {
                    try
                    {
                        mmf = MemoryMappedFile.OpenExisting(mapName);
                    }
                    catch
                    {
                        mmf = MemoryMappedFile.CreateNew(mapName, 数据大小);
                    }
                    访问器 = mmf.CreateViewAccessor();
                }
            }
            public static class 鼠标按键
            {
                private static int ID;
                public static bool isDispose = false;
                private static Mutex ___互斥锁;
                private unsafe static Data* data;
                private static int maxAppnum = 10;
                private static int maxArrayLength = 50;
                private static Mutex[] 工作钥匙 = new Mutex[maxAppnum];
                private static MemoryMappedFile[] 共享内存 = new MemoryMappedFile[5];
                private static EventWaitHandle[] 写入事件 = new EventWaitHandle[maxAppnum];

                static 鼠标按键()
                {
                    ___互斥锁 = new Mutex(false, nameof(鼠标按键) + 1, out var createdNew);
                    共享内存[0] = MemoryMappedFile.CreateOrOpen(nameof(鼠标按键) + 2, Marshal.SizeOf(typeof(Data)) * maxArrayLength);
                    共享内存[1] = MemoryMappedFile.CreateOrOpen(nameof(鼠标按键) + 3, Marshal.SizeOf(typeof(bool)) * maxAppnum);

                    if (createdNew)
                        共享内存[1].CreateViewAccessor().WriteArray(0, new bool[maxAppnum], 0, maxAppnum);

                    if (Process.GetCurrentProcess().ProcessName == "Moyu后台服务")
                    {
                        for (int i = 0; i < maxAppnum; i++)
                        {
                            写入事件[i] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(鼠标按键) + (i + 10));
                            工作钥匙[i] = new Mutex(false, nameof(鼠标按键) + (i + 20));
                        }
                    }
                    else
                    {
                        bool[] apps = new bool[maxAppnum];
                        共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);

                        ___互斥锁.WaitOne();
                        for (int i = 0; i < maxAppnum; i++)
                            if (!apps[i])
                            {
                                ID = i;
                                apps[i] = true;
                            }
                        ___互斥锁.ReleaseMutex();

                        写入事件[ID] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(鼠标按键) + (ID + 10));
                        工作钥匙[ID] = new Mutex(false, nameof(鼠标按键) + (ID + 20));
                        工作钥匙[ID].WaitOne();
                    }

                    unsafe
                    {
                        data = GetPtr<Data>(0);
                    }
                }
                [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                public unsafe static List<Data> GetData()
                {
                    List<Data> list = new List<Data>();
                    try
                    {
                        工作钥匙[ID].ReleaseMutex();
                        写入事件[ID].WaitOne();
                        工作钥匙[ID].WaitOne();
                        写入事件[ID].Reset();
                        for (int i = 0; i < maxArrayLength; i++)
                        {
                            if (data[i] != default)
                                list.Add(data[i]);
                            else
                                return list;
                        }
                    }
                    catch (System.ObjectDisposedException)
                    {
                        //锁已被释放
                    }
                    return list;
                }
                [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                public unsafe static void SetData(Span<Data> datas, bool keydown)
                {
                    for (int i = 0; i < maxArrayLength; i++)
                    {
                        if (i < datas.Length)
                            data[i] = datas[i];
                        else
                            data[i] = default;
                    }
                    data[0].KeyDown = keydown;

                    for (int i = 0; i < maxAppnum; i++)
                        写入事件[i].Set();

                    for (int i = 0; i < maxAppnum; i++)
                    {
                        工作钥匙[i].WaitOne();
                        工作钥匙[i].ReleaseMutex();
                    }
                }
                public unsafe static void Dispose()
                {
                    isDispose = true;
                    写入事件[ID].Close();
                    工作钥匙[ID].Close();

                    ___互斥锁.WaitOne();
                    bool[] apps = new bool[maxAppnum];
                    共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);
                    apps[ID] = false;
                    共享内存[1].CreateViewAccessor().WriteArray(0, apps, 0, maxAppnum);
                    ___互斥锁.ReleaseMutex();

                    foreach (var item in 共享内存)
                    {
                        if (item != null)
                            item.Dispose();
                    }
                    ___互斥锁.Dispose();
                }
                public struct Data
                {
                    public int Keys;
                    public bool KeyDown;
                    public Data(int Keys)
                    {
                        this.Keys = Keys;
                    }
                    public static bool operator ==(Data my1, Data my2)
                    {
                        return my1.Equals(my2);
                    }
                    public static bool operator !=(Data my1, Data my2)
                    {
                        return !(my1 == my2);
                    }
                }
                private unsafe static T* GetPtr<T>(int index)
                {
                    byte* v = default;
                    共享内存[index].CreateViewAccessor().SafeMemoryMappedViewHandle.AcquirePointer(ref v);
                    return (T*)v;
                }
            }


            // 声明钩子处理函数的委托
            private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
            private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

            // 导入用户32.dll中的函数
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool UnhookWindowsHookEx(IntPtr hhk);

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

            [StructLayout(LayoutKind.Sequential)]
            private struct MSLLHOOKSTRUCT
            {
                public Point pt;
                public uint mouseData;
                public uint flags;
                public uint time;
                public IntPtr dwExtraInfo;
            }

        }
    }
}
